<script lang="ts" module>
    export const TimepickerContextKey = Symbol("TimepickerContextKey");
    export const useTimepickerContext = () => getContext(TimepickerContextKey);
</script>

<script lang="ts">
    import { getContext, setContext, untrack } from "svelte";
    import { useClassList } from "../utils/useClassList";
    import type { TimePickerProps } from "./Timepicker";
    import dayjs from "dayjs";
    import type { Dayjs } from "dayjs";
    import { Dropdown } from "../Dropdown";
    import Value from "../Common/Value/Value.svelte";
    import Icon from "../Common/Icons/Icon.svelte";
    import TimePane from "./TimePane.svelte";
    import TimeRange from "./TimeRange.svelte";
    import { _ } from "svelte-i18n";
    import { useFormItemContext } from "../FormItem/FormItem.svelte";

    const { isDayjs } = dayjs;

    let { type, value = $bindable(type === "timeRange" ? [] : undefined) as Dayjs | Dayjs[] | undefined, ...props }: TimePickerProps = $props();
    const ctx = useFormItemContext();
    let v: Dayjs | Dayjs[] | undefined = $state();
    let visible = $state(false);

    const align = props.align ?? "bottomLeft";
    const format = props.format ?? "HH:mm:ss";
    const seperator = props.seperator || "~";
    const header = props.header ?? (type === "timeRange" ? [$_("Timepicker.headerStart"), $_("Timepicker.headerEnd")] : undefined);

    const classList = $derived(
        useClassList(props, "cm-time-picker", {
            "cm-time-picker-disabled": props.disabled,
            [`cm-time-picker-${props.theme}`]: props.theme,
            [`cm-time-picker-type-${type}`]: type,
            [`cm-time-picker-${props.size}`]: props.size,
            "cm-time-picker-clearable": !props.disabled && props.clearable && ((type === "timeRange" && (value as Dayjs[][0]) && (value as Dayjs[][1])) || value),
        })
    );

    $effect(() => {
        let val: Dayjs | Dayjs[] | undefined;
        if (value) {
            untrack(() => {
                if (typeof value === "string") {
                    val = dayjs(dayjs().format("YYYY-MM-DD ") + value);
                } else if (value instanceof Array) {
                    if (value[0] && typeof value[0] === "string") {
                        val = [dayjs(dayjs().format("YYYY-MM-DD ") + value[0], format), dayjs(dayjs().format("YYYY-MM-DD ") + value[1], format)];
                    } else {
                        val = value as Dayjs[] | undefined;
                    }
                } else {
                    val = value as Dayjs | undefined;
                }
            });
        }

        v = val;
    });

    const onSelect = (cellType: string, num: number, name: string) => {
        const now = dayjs();
        const origin = v || (type === "timeRange" ? [now, now] : now);
        if (type === "timeRange" && origin instanceof Array && !origin.length) {
            origin.push(now);
            origin.push(now);
        }

        let val: Dayjs;
        if (name === "start" && origin instanceof Array) {
            val = origin[0];
        } else if (name === "end" && origin instanceof Array) {
            val = origin[1];
        } else {
            val = origin as Dayjs;
        }

        if (cellType === "hour") {
            val = val.set("hour", num);
        }
        if (cellType === "minute") {
            val = val.set("minute", num);
        }
        if (cellType === "second") {
            val = val.set("second", num);
        }

        if (type === "timeRange") {
            let newVal: Dayjs[] = [];
            if (name === "start" && origin instanceof Array) {
                newVal = [dayjs(val), origin[1]];
            }
            if (name === "end" && origin instanceof Array) {
                newVal = [origin[0], dayjs(val)];
            }

            if (newVal[0].isAfter(newVal[1])) {
                newVal = [newVal[1], newVal[0]];
            }

            value = newVal;
            props.onchange?.(newVal);
            ctx?.onFieldChange?.();
        } else {
            const ret = dayjs(val);
            value = ret;
            props.onchange?.(ret);
            ctx?.onFieldChange?.();
        }
    };

    const onClear = () => {
        value = undefined;
        props.onchange?.(undefined);
        ctx?.onFieldChange?.();
    };

    const text = $derived.by(() => {
        const val = v;
        if (val) {
            if (isDayjs(val)) {
                return { title: val.format(format) };
            } else {
                if (val.length) {
                    return [{ title: dayjs(val[0]).format(format) }, { title: dayjs(val[1]).format(format) }];
                } else {
                    return { title: "" };
                }
            }
        }
        return { title: "" };
    });

    setContext(TimepickerContextKey, {
        onSelect,
        disabledTime: props.disabledTime,
        isVisible: () => visible,
    });
</script>

<div class={classList} x-placement={align} tabIndex="0">
    <Dropdown transfer={props.transfer} {align} trigger="click" disabled={props.disabled} bind:visible>
        {#snippet menu()}
            <div class="cm-time-picker-wrap">
                {#if type === "timeRange"}
                    <TimeRange value={v} {format} minuteStep={props.minuteStep} secondStep={props.secondStep} hourStep={props.hourStep} {header} footer={props.footer} />
                {:else}
                    <TimePane value={v} {format} minuteStep={props.minuteStep} secondStep={props.secondStep} hourStep={props.hourStep} {header} footer={props.footer} />
                {/if}
            </div>
        {/snippet}
        {#if !props.trigger}
            <Value prepend={props.prepend} {text} {onClear} range={type === "timeRange"} clearable={props.clearable} placeholder={props.placeholder} disabled={props.disabled} size={props.size}>
                {#snippet icon()}
                    <Icon icon="clock" />
                {/snippet}
            </Value>
        {:else}
            {@render props.trigger()}
        {/if}
    </Dropdown>
</div>
